package com.app.babygo.help;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.ShutterCallback;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class CameraHelper implements SurfaceHolder.Callback{
	private static final String TAG = "CameraHelper";
	protected Camera camera;
	protected byte[] jpeg_data;
	protected byte[] raw_data;
	protected boolean has_preview = false;
	protected String jpeg_filePath = null;
	
	public CameraHelper(){
		setupCamera();
	}

	public CameraHelper(SurfaceHolder holder){
		holder.addCallback(this);
	}
	
	public CameraHelper(SurfaceView view){
		SurfaceHolder holder = view.getHolder();
		holder.addCallback(this);
	}
	
	protected void setupCamera() {
		int numberOfCameras = Camera.getNumberOfCameras();
		int cameraId = 0;
	    for (int i = 0; i < numberOfCameras; i++) {
	      CameraInfo info = new CameraInfo();
	      Camera.getCameraInfo(i, info);
	      if (info.facing == CameraInfo.CAMERA_FACING_BACK) {
	        Log.d(TAG, "Camera found");
	        cameraId = i;
	        break;
	      }
	    }
		camera = Camera.open(cameraId);
		if (camera == null){
			Log.e(TAG, "No camera detected.");
			return;
		}
	}
	

	public void close() {
		if (camera != null) {
			camera.release();
			camera = null;
		}
	}
	
	public void startPreview() {
		if (camera == null) {
			Log.e(TAG, "No camera detected.");
			return;
		}
		if (has_preview) {
			camera.startPreview();
		}
	}
	
	public void stopPreview() {
		if (camera == null) {
			Log.e(TAG, "No camera detected.");
			return;
		}
		if (has_preview) {
			camera.stopPreview();
		}
	}

	public void takePicture() {
		if (camera == null) {
			Log.e(TAG, "No camera detected.");
			return;
		}
		camera.takePicture(shutterCallback, rawCallback, jpegCallback);
	}
	
	public void takePicture(String outputFilePath) {
		jpeg_filePath = outputFilePath; 
		takePicture();
	}
	
	public boolean saveAsJPEG(String filePath) {
		File file = new File(filePath);
		return saveAsJPEG(file);
	}
	public boolean saveAsJPEG(File file) {
		try {
			//Check file is write able or not
			if (!file.canWrite())
			{
				Log.e(TAG, "File: " + file.getAbsolutePath() + " is not writable.");
				//return false;
			}
			if (file.exists())
			{
				Log.e(TAG, "File: " + file.getAbsolutePath() + " exists.");
				//return false;
			}
			FileOutputStream outputStream = new FileOutputStream(file);
			outputStream.write(jpeg_data);
			outputStream.close();
			Log.d(TAG, "File saved at: " + file.getAbsolutePath());
		} catch (IOException e) {
			Log.e(TAG, "Error writing file: " + file.getAbsolutePath() + ", detail: " + e.getMessage());
			return false;
		}
		
		return true;
	}
	
	protected ShutterCallback shutterCallback = new ShutterCallback() {
		public void onShutter() {
			Log.d(TAG, "take a picture");
		}
	};
	
	protected PictureCallback rawCallback = new PictureCallback() {
		public void onPictureTaken(byte[] data, Camera camera) {
			raw_data = data;
		}
	};
	
	protected PictureCallback jpegCallback = new PictureCallback() {
		public void onPictureTaken(byte[] data, Camera camera) {
			jpeg_data = data;
			if (jpeg_filePath != null){
				saveAsJPEG(jpeg_filePath);
			}
		}
	};

	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
	
	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		setupCamera();
		try {
			camera.setPreviewDisplay(holder);
			has_preview = true;
			startPreview();
		} catch (IOException ex) {
			Log.e(TAG, ex.getMessage());
			has_preview = false;
		}
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		close();
	}
}
